package com.liuqianfei.markme.rules.block;

import com.liuqianfei.markme.core.Token;
import com.liuqianfei.markme.rules.AbstractState;
import com.liuqianfei.markme.rules.IAction;

import java.util.ArrayList;
import java.util.List;

/**
 * lheading (---, ===)
 * @author liuqianfei
 */
public class LheadingAction implements IAction
{
    @Override
    public boolean parse(AbstractState state, boolean silent, int startLine, int endLine)
    {
        String content;
        boolean terminate;
        int i;
        int l;
        Token token;
        int pos;
        int max;
        int level = 0;
        char marker = 0;
        int nextLine = startLine + 1;
        String oldParentType;
        List<IAction> terminatorRules = state.getMd().parserBlock.ruler.getRules("paragraph");

        oldParentType = state.getParentType();
        state.setParentType("paragraph"); // use paragraph to match terminatorRules

        // jump line-by-line until empty one or EOF
        for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++)
        {
            // this would be a code block normally, but after paragraph
            // it's considered a lazy continuation regardless of what's there
            if (state.getsCount(nextLine) - state.getBlkIndent() > 3)
                continue;

            //
            // Check for underline in setext header
            //
            if (state.getsCount(nextLine) >= state.getBlkIndent())
            {
                pos = state.getbMarks(nextLine) + state.gettShift(nextLine);
                max = state.geteMarks(nextLine);

                if (pos < max)
                {
                    marker = state.getSrc().charAt(pos);

                    if (marker == 0x2D/* - */ || marker == 0x3D/* = */)
                    {
                        pos = state.skipChars(pos, marker);
                        pos = state.skipSpaces(pos);

                        if (pos >= max)
                        {
                            level = (marker == 0x3D/* = */ ? 1 : 2);
                            break;
                        }
                    }
                }
            }

            // quirk for blockquotes, this line should already be checked by that rule
            if (state.getsCount(nextLine) < 0)
                continue;

            // Some tags can terminate paragraph without empty line.
            terminate = false;
            for (i = 0, l = terminatorRules.size(); i < l; i++)
            {
                if (terminatorRules.get(i).parse(state, true, nextLine, endLine))
                {
                    terminate = true;
                    break;
                }
            }
            if (terminate)
                break;
        }

        if (0 == level)
        {
            // Didn't find valid underline
            return false;
        }

        content = state.getLines(startLine, nextLine, state.getBlkIndent(), false).trim();

        state.setLine(nextLine + 1);

        token          = state.push("heading_open", "h" + String.valueOf(level), 1);
        token.markup   = String.valueOf(marker);
        token.map      = new int[]{startLine, state.getLine()};

        token          = state.push("inline", "", 0);
        token.content  = content;
        token.map      = new int[]{startLine, state.getLine() - 1};
        token.children = new ArrayList<>();

        token          = state.push("heading_close", "h" + String.valueOf(level), -1);
        token.markup   = String.valueOf(marker);

        state.setParentType(oldParentType);

        return true;
    }
}
